package zhou.chs.p5_1;

import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.Set;
import java.util.UUID;

public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener,View.OnClickListener,RadioGroup.OnCheckedChangeListener{
    //定义控件
    ListView lv;                  //列表显示蓝牙设备
    TextView tv;                  //显示设备NFC标签ID
    TextView tv1,tv2,tv3,tv4;   //显示测量值
    TextView tv5,tv6,tv7,tv8;   //显示保存值
    TextView tvSta;              //显示状态信息
    TextView tvRn;              //显示记录数
    Button btList,btSave;     //按键
    RadioGroup sel;             //测点选择
    RadioButton rb1;
    //变量定义
    private NfcAdapter mNfcAdapter;   //NFC适配器
    private PendingIntent pend;     	//异步调用
    private Tag tag;    				//标签
    private BluetoothAdapter btAdapter;         	//蓝牙适配器
    private BluetoothDevice btDevice;           	//蓝牙设备
    private Set<BluetoothDevice> pairedBts;     //配对蓝牙设备集合
    private BluetoothSocket btSocket = null;    //蓝牙socket
    private Handler myhandler;              		//信息通道
    private LinkThread mlink;               		//自定义连接线程
    private ComThread mcom;                 		//自定义数据通信线程
    UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    public byte rbuf[] = new byte[64];        	//接收缓冲区
    int len;   //接收字节长度
    private boolean isConnect;   //已连接状态
    private boolean ss;//轮流显示

    String db_name="mdb";  //数据库名称
    String tb_name="xj";   //巡检数据表
    SQLiteDatabase db; //数据库
    private Date now; //日期
    String ndata,ntime,nid; //记录中的日期、时间、设备ID
    int sz[] = new int[16];
    int msel=0; //测点选择：0-测点1  1-测点2  2-测点3  3-测点4
    int mx,my,mz,mt;    //当前测量值
    int rn=0;   //记录数
    Cursor cp;  //数据记录指针
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.idtv);    //控件实例化
        tv1 = (TextView) findViewById(R.id.idtv1);
        tv2 = (TextView) findViewById(R.id.idtv2);
        tv3 = (TextView) findViewById(R.id.idtv3);
        tv4 = (TextView) findViewById(R.id.idtv4);
        tv5 = (TextView) findViewById(R.id.idtv5);
        tv6 = (TextView) findViewById(R.id.idtv6);
        tv7 = (TextView) findViewById(R.id.idtv7);
        tv8 = (TextView) findViewById(R.id.idtv8);
        tvSta = (TextView) findViewById(R.id.idtv9);
        tvRn = (TextView) findViewById(R.id.idtv10);
        btSave = (Button) findViewById(R.id.idSave);
        btList = (Button) findViewById(R.id.idList);
        btSave.setOnClickListener(this);    //注册按钮单击监听事件
        btList.setOnClickListener(this);
        rb1=(RadioButton) findViewById(R.id.idrb1);
        lv = (ListView) findViewById(R.id.idbl);
        lv.setOnItemClickListener(this);
        sel=(RadioGroup)findViewById(R.id.radioGroup);
        sel.setOnCheckedChangeListener(this);     //注册RadioGroup选择事件
        myhandler = new MyHandler();        //实例化Handler，用于进程间的通信
        btAdapter = BluetoothAdapter.getDefaultAdapter();   //蓝牙适配器
        //屏幕常亮
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        //建立数据库
        db=openOrCreateDatabase(db_name, Context.MODE_PRIVATE,null);
        //生成记录表
        String createTable="CREATE TABLE IF NOT EXISTS " + tb_name +
                "(mdate VARCHAR(20),mtime VARCHAR(10),id VARCHAR(10)," +
                "x1 INTEGER,y1 INTEGER,z1 INTEGER,t1 INTEGER," +
                "x2 INTEGER,y2 INTEGER,z2 INTEGER,t2 INTEGER," +
                "x3 INTEGER,y3 INTEGER,z3 INTEGER,t3 INTEGER," +
                "x4 INTEGER,y4 INTEGER,z4 INTEGER,t4 INTEGER)";
        db.execSQL(createTable);
        btSave.setEnabled(false);  //禁止保存按钮，扫描到NFC标签后才可使用
        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);   //获取NFC适配器
        //监听NFC标签，发现后发送一个Intent给当前Activity，调用onNewIntent方法
        pend = PendingIntent.getActivity(this, 0, new Intent(this,
                getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

    }
    // 启动NFC监听
    protected void onResume() {
        super.onResume();
        mNfcAdapter.enableForegroundDispatch(this, pend, null, null);
    }
    // NFC监听响应，
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        tag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);//获取到Tag标签对象
        if(tag!=null){
            byte[] rfid = new byte[4];
            String strid = "";
            rfid=tag.getId();  //获得标签ID
            for(int i=0;i<4;i++) strid+=String.format("%02X",rfid[i]);
            rn++;
            btSave.setEnabled(true);
            now = new Date();
            ndata = String.format("%tF",now);  //获得当前日期
            ntime = String.format("%tT",now);  //获得当前时间
            nid = strid;
            for(int i=0;i<16;i++) sz[i]=0;
            add(ndata,ntime,nid,sz);  //新建巡检记录
            rb1.setChecked(true);
            tv.setText(nid);      //显示设备NFC标签ID
            tvRn.setText("记录数：" + rn); //刷新记录数
        }else{
            return;
        }
    }
    // 添加记录
    private void add(String mdate, String mtime,String id,int sz[]) {
        ContentValues cv=new ContentValues(15); //
        cv.put("mdate", mdate);
        cv.put("mtime", mtime);
        cv.put("id", id);
        cv.put("x1", sz[0]);
        cv.put("y1", sz[1]);
        cv.put("z1", sz[2]);
        cv.put("t1", sz[3]);
        cv.put("x2", sz[4]);
        cv.put("y2", sz[5]);
        cv.put("z2", sz[6]);
        cv.put("t2", sz[7]);
        cv.put("x3", sz[8]);
        cv.put("y3", sz[9]);
        cv.put("z3", sz[10]);
        cv.put("t3", sz[11]);
        cv.put("x4", sz[12]);
        cv.put("y4", sz[13]);
        cv.put("z4", sz[14]);
        cv.put("t4", sz[15]);
        db.insert(tb_name, null, cv);
    }
    //响应按键单击事件
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.idList:        //蓝牙列表按钮
                pairedBts = btAdapter.getBondedDevices();   //获得已配对蓝牙设备集合
                ArrayList bt_list = new ArrayList();
                lv.setEnabled(true);
                if (!btAdapter.isEnabled()) {           //当前蓝牙适配器不可用
                    Intent turnOn = new
                            Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                    startActivityForResult(turnOn, 0);    //调用打开蓝牙适配器程序
                    tvSta.setText("打开蓝牙适配器");
                } else {
                    tvSta.setText("蓝牙适配器已打开");
                }
                for(BluetoothDevice bt : pairedBts){ //已配对蓝牙设备集合转为列表
                    bt_list.add(bt.getName() + "\n" + bt.getAddress());
                }               //列表放入适配器
                final ArrayAdapter adapter = new ArrayAdapter
                        (this, android.R.layout.simple_list_item_1, bt_list);
                lv.setAdapter(adapter);  //通过适配器在ListView上显示配对蓝牙设备列表
                tvSta.setText("选择蓝牙设备");
                break;
            case R.id.idSave:          //保存按钮
                ContentValues cv = new ContentValues();
                if(msel==0){    //保存测点1数据
                    sz[0]=mx;
                    sz[1]=my;
                    sz[2]=mz;
                    sz[3]=mt;
                    cv.put("x1", sz[0]);
                    cv.put("y1", sz[1]);
                    cv.put("z1", sz[2]);
                    cv.put("t1", sz[3]);
                }
                else if(msel==1){  //保存测点2数据
                    sz[4]=mx;
                    sz[5]=my;
                    sz[6]=mz;
                    sz[7]=mt;
                    cv.put("x2", sz[4]);
                    cv.put("y2", sz[5]);
                    cv.put("z2", sz[6]);
                    cv.put("t2", sz[7]);
                }
                else if(msel==2){  //保存测点3数据
                    sz[8]=mx;
                    sz[9]=my;
                    sz[10]=mz;
                    sz[11]=mt;
                    cv.put("x3", sz[8]);
                    cv.put("y3", sz[9]);
                    cv.put("z3", sz[10]);
                    cv.put("t3", sz[11]);
                }
                else if(msel==3){   //保存测点4数据
                    sz[12]=mx;
                    sz[13]=my;
                    sz[14]=mz;
                    sz[15]=mt;
                    cv.put("x4", sz[12]);
                    cv.put("y4", sz[13]);
                    cv.put("z4", sz[14]);
                    cv.put("t4", sz[15]);
                }
                //更新当前记录测得数据
                db.update(tb_name,cv, "mtime=? AND id=?", new String[]{ntime,nid});
                show(); //显示新保存数据
                break;
        }
    }
    //响应列表单击选项事件
    public void onItemClick(AdapterView<?> parent, View view, int position,long id) {
        TextView txv = (TextView) view;  //获取选中项文本
        String s = txv.getText().toString();
        String[] addr = s.split("\n");   //抽取MAC地址
        try {        //通过MAC地址获得蓝牙设备
            btDevice = btAdapter.getRemoteDevice(addr[1]);
            lv.setEnabled(false);
        } catch (Exception e) {
            tvSta.setText("获取设备失败");
        }
        mlink = new LinkThread(btDevice);  //在蓝牙设备连接线程中加载蓝牙设备
        mlink.start();   //启动连接蓝牙设备线程
    }
    @Override  // 响应RadioGroup选择事件
    public void onCheckedChanged(RadioGroup radioGroup, int i) {
        switch (i) {
            case R.id.idrb1:
                msel=0; //测点1
                break;
            case R.id.idrb2:
                msel=1; //测点2
                break;
            case R.id.idrb3:
                msel=2; //测点3
                break;
            case R.id.idrb4:
                msel=3; //测点4
                break;
        }
        show();  //刷新选择测点的记录值
    }
    //显示已保存数据
    public void show() {
        switch (msel) {
            case 0:
                tv5.setText(String.format("%.1f", (float)sz[0]/10));
                tv6.setText(String.format("%.1f", (float)sz[1]/10));
                tv7.setText(String.format("%.1f", (float)sz[2]/10));
                tv8.setText(String.format("%d", sz[3]));
                break;
            case 1:
                tv5.setText(String.format("%.1f", (float)sz[4]/10));
                tv6.setText(String.format("%.1f", (float)sz[5]/10));
                tv7.setText(String.format("%.1f", (float)sz[6]/10));
                tv8.setText(String.format("%d", sz[7]));
                break;
            case 2:
                tv5.setText(String.format("%.1f", (float)sz[8]/10));
                tv6.setText(String.format("%.1f", (float)sz[9]/10));
                tv7.setText(String.format("%.1f", (float)sz[10]/10));
                tv8.setText(String.format("%d", sz[11]));
                break;
            case 3:
                tv5.setText(String.format("%.1f", (float)sz[12]/10));
                tv6.setText(String.format("%.1f", (float)sz[13]/10));
                tv7.setText(String.format("%.1f", (float)sz[14]/10));
                tv8.setText(String.format("%d", sz[15]));
                break;
        }
    }
    //连接蓝牙装置
    private class LinkThread extends Thread {
        public LinkThread(BluetoothDevice mDevice) {
            btSocket = null;
            try {   //定义Socket为蓝牙串口服务
                btSocket = mDevice.createRfcommSocketToServiceRecord(uuid);
            } catch (Exception e) {
            }
        }
        public final void run() {
            btAdapter.cancelDiscovery();
            try {
                btSocket.connect();       //建立Socket连接
                isConnect = true;
                mcom = new ComThread(btSocket);
                mcom.start();       		//建立连接后启动建立数据通信线程
                Message msg = myhandler.obtainMessage();
                msg.what = 1;
                myhandler.sendMessage(msg);    //通知主线程可以开始通信
            } catch (IOException e1) {
                isConnect = false;
                try {
                    btSocket.close();   //关闭蓝牙连接
                    btSocket = null;
                } catch (IOException e2) {
                }
            }
        }
    }
    //在主线程处理Handler传回来的message
    class MyHandler extends Handler {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:   //成功连接蓝牙
                    tvSta.setText("已连接蓝牙");
                    cp = db.query(tb_name, null, null, null, null, null, null);
                    rn=cp.getCount();   //获得记录数
                    tvRn.setText("记录数：" + rn);
                    break;
                case 2:     //收到蓝牙数据
                    len=0;
                    //传感器数据
                    if((rbuf[1]==0x03)&&(rbuf[2]==0x06)){
                        //显示监测数据
                        mx = rbuf[3]&(0xFF);
                        tv1.setText(String.format("%.1f", (float)mx/10));
                        my =rbuf[4]&(0xFF);
                        tv2.setText(String.format("%.1f", (float)my/10));
                        mz =rbuf[5]&(0xFF);
                        tv3.setText(String.format("%.1f", (float)mz/10));
                        mt = rbuf[7]&(0xFF);
                        tv4.setText(String.format("%d", mt));
                        int m = rbuf[8]&(0xFF);
                        ss=!ss;     //轮流显示信息，说明蓝牙连接正常，能不断接收到数据
                        if(ss) tvSta.setText(String.format("电池%.1f", (float)m/10)+"V");
                        else tvSta.setText("收到传感器数据");
                    }
                    //上位机查询记录数
                    if((rbuf[1]==0x03)&&(rbuf[2]==0x00)&&(rbuf[3]==0x00)){
                        cp = db.query(tb_name, null, null, null, null, null, null);
                        rn=cp.getCount();
                        byte tbuf[] = new byte[7];        	//发送缓冲区
                        tbuf[0]=(byte) 0xFF;
                        tbuf[1]=(byte) 0x03;
                        tbuf[2]=(byte) 0x02;
                        tbuf[3]=(byte)((rn>>8)&0xFF);
                        tbuf[4]=(byte)(rn&0xFF);
                        int crc = CRC16(tbuf,5);
                        tbuf[5]=(byte)(crc&0xFF);
                        tbuf[6]=(byte)((crc>>8)&0xFF);
                        mcom.write(tbuf);      //返回记录数
                        tvSta.setText("已连接上位机");
                    }
                    //上位机删除记录
                    if((rbuf[1]==0x06)&&(rbuf[2]==0x00)&&(rbuf[3]==0x00)){
                        db.delete(tb_name, null, null);
                        rn=0;
                        tvRn.setText("记录数：" + rn);
                        tvSta.setText("记录已删除");
                    }
                    //上位机调取记录
                    if((rbuf[1]==0x03)&&(rbuf[2]==0x00)&&((rbuf[3]&0xFF)>0x00)){
                        int n = rbuf[3]&0xFF;
                        cp.moveToFirst();
                        for(int i=1;i<n;i++) cp.moveToNext();
                        byte tbuf[] = new byte[28];        	//发送缓冲区
                        tbuf[0]=(byte)(n & 0xFF); //序号
                        String s=cp.getString(0);
                        String[] sn = s.split("-");
                        tbuf[1]=(byte)(Integer.parseInt(sn[1])&0xFF);   //月
                        tbuf[2]=(byte)(Integer.parseInt(sn[2])&0xFF);   //日
                        s=cp.getString(1);
                        sn = s.split(":");
                        tbuf[3]=(byte)(Integer.parseInt(sn[0])&0xFF);   //时
                        tbuf[4]=(byte)(Integer.parseInt(sn[1])&0xFF);   //分
                        tbuf[5]=(byte)(Integer.parseInt(sn[2])&0xFF);   //秒
                        s=cp.getString(2);
                        for (int i = 0; i < 8; i += 2) {
                            // 两位一组，表示一个字节,把这样表示的16进制字符串，还原成一个字节
                            tbuf[i / 2+6] = (byte) ((Character.digit(s.charAt(i),
                                    16) << 4) + Character.digit(s.charAt(i + 1), 16));
                        }
                        for(int i=0;i<16;i++) tbuf[10+i] = (byte)(cp.getInt(i+3)&0xFF);
                        int crc = CRC16(tbuf,26);
                        tbuf[26]=(byte)(crc&0xFF);
                        tbuf[27]=(byte)(crc>>8);
                        mcom.write(tbuf);      //发送记录数据
                        tvSta.setText("上传记录：" + n);
                    }
                    break;
            }
        }
    }
    //数据通信线程
    private class ComThread extends Thread {
        private final BluetoothSocket mSocket;
        private final InputStream mInStream;    //定义输入流
        private final OutputStream mOutStream;  //定义输出流
        public ComThread(BluetoothSocket socket) {   //socket连接
            mSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;
            try {
                tmpIn = mSocket.getInputStream();      //Socket输入数据流
                tmpOut = mSocket.getOutputStream();    //Socket输出数据流
            } catch (IOException e) {
            }
            mInStream = tmpIn;
            mOutStream = tmpOut;
        }
        //阻塞线程接收数据
        public final void run() {
            byte[] buf = new byte[512];  // 接收数据临时缓冲区
            while (isConnect) {
                try {
                    int byt = mInStream.read(buf);
                    for (int i = 0; i < byt; i++) rbuf[len + i] = buf[i];  // 收到数据后转移到待处理存储区
                    len = len + byt;         //数据分段接收，字节数累计
                    if (len > 7) {
                        Message msg = myhandler.obtainMessage();
                        msg.what = 2;
                        myhandler.sendMessage(msg); // 通知主线程接收到数据
                    }
                    try {
                        sleep(50);     //延时50ms，等接收区数据处理完毕
                    } catch (InterruptedException e) {
                    }
                } catch (NullPointerException e) {
                    isConnect = false;
                    break;
                } catch (IOException e) {
                    break;
                }
            }
        }
        //发送字节数据
        public void write(byte[] bytes) {
            try {
                mOutStream.write(bytes);
            } catch (IOException e) {
            }
        }
        //关闭蓝牙连接
        public void cancel() {
            try {
                mSocket.close();
            } catch (IOException e) {
            }
        }
    }
    //CRC校验
    public int CRC16(byte dat[],int len)
    {
        int CRC=0xFFFF;
        int temp;
        int i,j;
        for( i = 0; i<len; i ++)
        {
            temp = dat[i];
            if(temp < 0) temp += 256;
            temp &= 0xFF;
            CRC^= temp;
            for (j = 0; j<8; j++)
            {
                if ((CRC & 0x0001) == 0x0001)
                    CRC=(CRC>>1)^0xA001;
                else
                    CRC >>=1;
            }
        }
        return (CRC&0xffff);
    }
    //取消监听
    protected void onPause() {
        super.onPause();
        if (mNfcAdapter != null) {
            mNfcAdapter.disableForegroundDispatch(this);
        }
    }
}
